﻿using System;
using System.IO;
using System.Windows.Forms;
using Moonlite.Platform.General;
using Moonlite.Platform.Project;
using Moonlite.ExtensionApi;
using Moonlite.ExtensionApi.GlobalInterfaces;

namespace Moonlite.Compiling
{
    public class LibraryManager : ILibraryManager
    {
        private static LibraryManager instance;
        public static LibraryManager Instance
        {
            get { return instance; }
        }

        private const string FilesComment = "#start files";
        private string GetProjectTable(IProject project)
        {
            string newLine = Environment.NewLine;
            string table = project.Name + newLine + project.Path + newLine + project.Version + newLine + project.Description + newLine;
            string typeName = Enum.GetName(typeof(ProjectType), project.Type);
            table += typeName + newLine;
            project.References.ForEach(reference => table += reference + newLine);
            return table;
        }

        private string ReadProjectTable(string fileContents, CompiledLibrary library)
        {
            int commentIndex = fileContents.IndexOf(FilesComment);
            if (commentIndex > -1)
            {
                string table = fileContents.Substring(0, commentIndex);
                fileContents = fileContents.Substring(commentIndex + FilesComment.Length + Environment.NewLine.Length);
                string[] tableSplit = table.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
                library.Name = tableSplit[0];
                library.Path = tableSplit[1];
                library.Version = tableSplit[2];
                library.Description = tableSplit[3];
                ProjectType type = ProjectType.Jass;
                try { type = (ProjectType)Enum.Parse(typeof(ProjectType), tableSplit[4]); }
                catch (Exception exception) { Logger.Log += exception.Message + Environment.NewLine; }
                library.Type = type;
                for (int index = 4; index < tableSplit.Length - 5; index++)
                {
                    library.References.Add(tableSplit[index]);
                }
            }

            return fileContents;
        }

        public void BuildLibrary(IProject project)
        {
            string binPath = project.GetBinFolderPath();
            DirectoryHelper.CreateFolderPath(binPath);
            try
            {
                string path = String.Format("{0}\\{1}.{2}", binPath, project.Name, Global.CompiledLibraryExtension);
                string tempPath = path + ".temp";
                if (File.Exists(tempPath) == true) File.Delete(tempPath);
                using (StreamWriter writer = new StreamWriter(File.Open(tempPath, FileMode.OpenOrCreate)))
                {
                    string fileContents = GetProjectTable(project) + FilesComment + Environment.NewLine;
                    foreach (ProjectFile file in project.GetAllFiles())
                    {
                        if (File.Exists(file.Path) == true && Path.GetExtension(file.Path).Substring(1) == project.GetProjectFileExtension())
                        {
                            using (StreamReader reader = new StreamReader(file.Path))
                            {
                                fileContents += reader.ReadToEnd() + "\0";
                            }
                        }
                    }

                    writer.Write(fileContents);
                }

                CompressionUtils.Compress(new FileInfo(tempPath), path);
                File.Delete(tempPath);
            }
            catch (Exception exception)
            {
                Logger.Log += exception.Message + Environment.NewLine;
                ShowError(String.Format("An error occurred while building library: {0}{1}", Environment.NewLine, exception.Message));
            }
        }

        public CompiledLibrary ReadLibrary(string path)
        {
            CompiledLibrary library = new CompiledLibrary();
#if (!DEBUG)
            try
            {
#endif
            CompressionUtils.Decompress(new FileInfo(path));
            using (StreamReader reader = new StreamReader(File.Open(path + ".temp", FileMode.Open)))
            {
                int readIndex = 0;
                string fileContents = reader.ReadToEnd();
                fileContents = ReadProjectTable(fileContents, library);
                string[] files = fileContents.Split('\0');
                Array.ForEach(files, library.Files.Add);
                readIndex++;
            }

            File.Delete(path + ".temp");
#if (!DEBUG)
            }
            catch (Exception exception)
            {
                Logger.Log += exception.Message + Environment.NewLine;
                ShowError(String.Format("An error occurred while building library: {0}{1}", Environment.NewLine, exception.Message));
            }
#endif

            return library;
        }

        private static void ShowError(string message)
        {
            MessageBox.Show(message, "Moonlite Map Studio", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
        }

        private LibraryManager()
        {
            try { Global.Instance.RegisterService(this, GetType().GetInterface("ILibraryManager")); }
            catch { }
        }

        static LibraryManager()
        {
            instance = new LibraryManager();
        }
    }
}
